From 77598c0f3df56ea8d2e98c0f557f9de3029d3b65 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 19 Nov 2010 13:45:08 +0000 Subject: [PATCH] Introduce PHYSDEVOP_get_free_pirq Introduce a new physdev_op called PHYSDEVOP_get_free_pirq to allow a guest to get a free pirq number from Xen; the hypervisor would keep that pirq free for the guest to use in a mapping. Signed-off-by: Stefano Stabellini --- xen/arch/x86/hvm/hvm.c | 2 ++ xen/arch/x86/irq.c | 2 +- xen/arch/x86/physdev.c | 22 +++++++++++++++++++++- xen/arch/x86/x86_64/physdev.c | 3 +++ xen/include/asm-x86/irq.h | 1 + xen/include/public/physdev.h | 15 +++++++++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 3d94c8736e..bb50b61131 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2448,6 +2448,7 @@ static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_unmap_pirq: case PHYSDEVOP_eoi: case PHYSDEVOP_irq_status_query: + case PHYSDEVOP_get_free_pirq: return do_physdev_op(cmd, arg); default: return -ENOSYS; @@ -2550,6 +2551,7 @@ static long hvm_physdev_op_compat32( case PHYSDEVOP_unmap_pirq: case PHYSDEVOP_eoi: case PHYSDEVOP_irq_status_query: + case PHYSDEVOP_get_free_pirq: return compat_physdev_op(cmd, arg); break; default: diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index ec74698c36..6ac0cd3438 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1505,7 +1505,7 @@ int map_domain_pirq( old_irq = domain_pirq_to_irq(d, pirq); old_pirq = domain_irq_to_pirq(d, irq); - if ( (old_irq && (old_irq != irq) ) || + if ( (old_irq > 0 && (old_irq != irq) ) || (old_pirq && (old_pirq != pirq)) ) { dprintk(XENLOG_G_WARNING, "dom%d: pirq %d or irq %d already mapped\n", diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 453b4f3006..2913a9c1b7 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -121,7 +121,7 @@ static int physdev_map_pirq(struct physdev_map_pirq *map) } irq = domain_pirq_to_irq(current->domain, map->index); - if ( !irq ) + if ( irq <= 0 ) { if ( IS_PRIV(current->domain) ) irq = map->index; @@ -557,6 +557,26 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) setup_gsi.polarity); break; } + case PHYSDEVOP_get_free_pirq: { + struct physdev_get_free_pirq out; + struct domain *d; + + d = rcu_lock_current_domain(); + + ret = -EFAULT; + if ( copy_from_guest(&out, arg, 1) != 0 ) + break; + + spin_lock(&d->event_lock); + out.pirq = get_free_pirq(d, out.type, 0); + d->arch.pirq_irq[out.pirq] = PIRQ_ALLOCATED; + spin_unlock(&d->event_lock); + + ret = copy_to_guest(arg, &out, 1) ? -EFAULT : 0; + + rcu_unlock_domain(d); + break; + } default: ret = -ENOSYS; break; diff --git a/xen/arch/x86/x86_64/physdev.c b/xen/arch/x86/x86_64/physdev.c index d20eafcaff..e3db9386b5 100644 --- a/xen/arch/x86/x86_64/physdev.c +++ b/xen/arch/x86/x86_64/physdev.c @@ -42,6 +42,9 @@ #define physdev_manage_pci compat_physdev_manage_pci #define physdev_manage_pci_t physdev_manage_pci_compat_t +#define physdev_get_free_pirq compat_physdev_get_free_pirq +#define physdev_get_free_pirq_t physdev_get_free_pirq_compat_t + #define COMPAT #undef guest_handle_okay #define guest_handle_okay compat_handle_okay diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 078aa537c0..af6b8acc2e 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -150,6 +150,7 @@ void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); #define domain_pirq_to_irq(d, pirq) ((d)->arch.pirq_irq[pirq]) #define domain_irq_to_pirq(d, irq) ((d)->arch.irq_pirq[irq]) +#define PIRQ_ALLOCATED -1 #define domain_pirq_to_emuirq(d, pirq) ((d)->arch.pirq_emuirq[pirq]) #define domain_emuirq_to_pirq(d, emuirq) ((d)->arch.emuirq_pirq[emuirq]) #define IRQ_UNBOUND -1 diff --git a/xen/include/public/physdev.h b/xen/include/public/physdev.h index 18d30593c6..82602ca6dc 100644 --- a/xen/include/public/physdev.h +++ b/xen/include/public/physdev.h @@ -240,6 +240,21 @@ struct physdev_setup_gsi { typedef struct physdev_setup_gsi physdev_setup_gsi_t; DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t); +/* leave PHYSDEVOP 22 free */ + +/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI + * the hypercall returns a free pirq */ +#define PHYSDEVOP_get_free_pirq 23 +struct physdev_get_free_pirq { + /* IN */ + int type; + /* OUT */ + uint32_t pirq; +}; + +typedef struct physdev_get_free_pirq physdev_get_free_pirq_t; +DEFINE_XEN_GUEST_HANDLE(physdev_get_free_pirq_t); + /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- 2.30.2